package com.example.version.controll.util;

import com.example.version.controll.model.ConfigDTO;
import com.example.version.controll.model.ProjectDTO;
import com.example.version.controll.model.ProjectVersion;
import com.example.version.controll.eo.TypeEO;
import com.example.version.controll.model.RepositoryConfig;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.springframework.util.StringUtils;

import java.io.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class FileUtil {

    public static ConfigDTO configDTO;
    public static Map<String, ProjectDTO> projectDTOMap;
    public static List<String> gradleSort;
    public static Map<String, GitUtil> gitUtilMap;

    public static String maxVersion = "0.0.0";

    static {
        File file = new File(PathManagerUtil.configPath);
        if (!file.exists()) {
            try {
                file.createNewFile();
                ConfigDTO configDTO1 = new ConfigDTO();
                configDTO1.setUserName("userName");
                configDTO1.setPassWord("123456");
                List<RepositoryConfig> list = new ArrayList<>();
                configDTO1.setRepositoryList(list);
                writeContent2File(PathManagerUtil.configPath, JsonUtil.toJsonString(configDTO1));
            } catch (IOException e) {
            }
        }
        initConfig();
        PathManagerUtil.gradleSortPath += PathManagerUtil.basePath + "/gradleSort.txt";
        file = new File(PathManagerUtil.gradleSortPath);
        if (!file.exists()) {
            try {
                file.createNewFile();
            } catch (IOException e) {
            }
        }
        initGradleSort();
        initGitData();
        initProject();
    }

    public static void initProject() {
        List<RepositoryConfig> repositoryList = configDTO.getRepositoryList();
        if (projectDTOMap == null) {
            projectDTOMap = new HashMap<>();
        }
        projectDTOMap.clear();
        for (RepositoryConfig repositoryConfig : repositoryList) {
            List<ProjectDTO> projectList = repositoryConfig.getProjectList();
            if (CollectionUtils.isEmpty(projectList)) {
                projectList = new ArrayList<>();
                repositoryConfig.setProjectList(projectList);
            }
            for (ProjectDTO projectDTO : projectList) {
                projectDTOMap.put(projectDTO.getName(), projectDTO);
            }
        }
    }

    public static void initGitData(){
        List<RepositoryConfig> repositoryList = configDTO.getRepositoryList();
        if (gitUtilMap == null) {
            gitUtilMap = new HashMap<>();
        }
        gitUtilMap.clear();
        for (RepositoryConfig repositoryConfig : repositoryList) {
            try {
                GitUtil gitUtil = new GitUtil(repositoryConfig);
                gitUtilMap.put(repositoryConfig.getName(), gitUtil);
                repositoryConfig.setGitUtil(gitUtil);
            } catch (Exception e) {
                System.out.println("初始化仓库失败" + JsonUtil.toJsonString(repositoryConfig));
            }
        }
    }

    public static void initGradleSort() {
        gradleSort = new ArrayList<>();
        String s = readFile2Content(PathManagerUtil.gradleSortPath);
        if (StringUtils.hasText(s)) {
            List<String> list = JsonUtil.toObject(s, List.class);
            if (list != null) {
                gradleSort = list;
            }
        }
    }

    public static void initConfig() {
        configDTO = new ConfigDTO();
        String s = readFile2Content(PathManagerUtil.configPath);
        if (StringUtils.hasText(s)) {
            ConfigDTO configDTO1 = JsonUtil.toObject(s, ConfigDTO.class);
            if (configDTO1 != null) {
                configDTO = configDTO1;
            }
        }
    }

    public static void writeContent2File(String path, String content) {
        File file = new File(path);
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(file);
            fos.write(content.getBytes("UTF-8"));
            fos.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void exitCreateOrUpdate(String path, String content, boolean create) {
        File file = new File(path);
        if (!file.exists()) {
            file.mkdirs();
            FileUtil.writeContent2File( path, content);
        } else {
            if (create) {
                file.delete();
                try {
                    file.createNewFile();
                } catch (IOException e) {
                }
                FileUtil.writeContent2File( path, content);
            }
        }
    }

    /**
     * 获取文件全部内容
     * @param path 文件路径
     * @return 如果文件不存在 或内容为空 就返回null
     */
    public static String readFile2Content(String path) {
        File file = new File(path);
        if (file.exists() && file.length() > 0) {
            FileInputStream fis = null;
            try {
                fis = new FileInputStream(file);
                byte[] content = new byte[((Long)file.length()).intValue()];
                fis.read(content);
                fis.close();
                return new String(content, "UTF-8");
            } catch (Exception e) {
                return null;
            } finally {
                if (fis != null) {
                    try {
                        fis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return null;
    }

    public static void findBuild() {
        Map<String, List<ProjectDTO>> map = new HashMap<>();
        FileUtil.findBuild(PathManagerUtil.gitDataPath, null, "", map);
        List<RepositoryConfig> repositoryList = configDTO.getRepositoryList();
        for (RepositoryConfig repositoryConfig : repositoryList) {
            List<ProjectDTO> projectDTOS = map.get(repositoryConfig.getName());
            repositoryConfig.setProjectList(projectDTOS);
        }
        reloadConfig();
    }

    public static void findBuild(String path, String projectName, String absolutePathh, Map<String, List<ProjectDTO>> map) {
        File file = new File(path);
        if (!file.exists()) {
            return;
        }
        if (file.isFile()) {
            return;
        }
        File[] files = file.listFiles();
        for (File children : files) {
            boolean isFirst = !StringUtils.hasText(projectName);
            String tempName = projectName;
            if (children.isDirectory()) {
                if (!StringUtils.hasText(tempName)) {
                    tempName = children.getName();
                }
                findBuild(children.getAbsolutePath(), tempName, (isFirst ? "" : absolutePathh) + children.getName() + "/", map);
                continue;
            }
            if (children.isFile() && "build.gradle".equals(children.getName())) {
                ProjectDTO projectDTO = new ProjectDTO();
                projectDTO.setName(file.getName());
                projectDTO.setPath(children.getAbsolutePath());
                projectDTO.setType("");
                projectDTO.setProjectName(projectName);
                projectDTO.setBuildAbsolutePath(absolutePathh.replaceFirst(projectName + "/", "") + "build.gradle");
                List<ProjectDTO> projectDTOS = map.get(projectName);
                if (CollectionUtils.isEmpty(projectDTOS)) {
                    projectDTOS = new ArrayList<>();
                }
                projectDTOS.add(projectDTO);
                map.put(projectName, projectDTOS);
            }
        }
    }

    public static final String BOM_REGX = "(implementation platform\\(\"com\\.nfdw\\.xtbg:oa-bom:[0-9]{1,}\\.[0-9]{1,}\\.[0-9]{1,}-SNAPSHOT\"\\))";
    public static final String API_REGX = "def artifactId = \"[*]{1,}\"";
    public static final String VERSION_REGX = "(version [\"'][[0-9]{1,}\\.]{1,}-SNAPSHOT[\"'])";
    public static final Pattern bomCompile = Pattern.compile(BOM_REGX);
    public static final Pattern versionCompile = Pattern.compile(VERSION_REGX);

    public static void checkType() {
        if (MapUtils.isEmpty(projectDTOMap)) {
            return;
        }
        List<RepositoryConfig> repositoryList = configDTO.getRepositoryList();
        for (RepositoryConfig repositoryConfig : repositoryList) {
            List<ProjectDTO> projectList = repositoryConfig.getProjectList();
            repositoryConfig.setProjectList(projectList.stream().filter(x -> {
                String content = readFile2Content(x.getPath());
                if (!StringUtils.hasText(content)) {
                    return false;
                }
                Matcher matcher = bomCompile.matcher(content);
                if (!matcher.find()) {
                    return false;
                }
                if (content.contains("def artifactId = \"")) {
                    x.setType("api");
                    String uploadGradle = "@echo off \n" +
                            "cd " + x.getPath().substring(0, x.getPath().lastIndexOf("\\")) + " \n" +
                            "gradle uploadArchives  ";
                    File file = new File(PathManagerUtil.batPath + x.getProjectName());
                    if (!file.exists()) {
                        file.mkdirs();
                    }
                    FileUtil.exitCreateOrUpdate(PathManagerUtil.batPath + x.getProjectName() + "/"
                            + x.getName() + "-" + TypeEO.GRADLE.getName(), uploadGradle, true);
                } else {
                    x.setType("server");
                }
                return true;
            }).collect(Collectors.toList()));
        }
        reloadConfig();
    }

    public static Map<String, ProjectVersion> findVersion() {
        if (MapUtils.isEmpty(projectDTOMap)) {
            return new HashMap<>();
        }
        Map<String, ProjectVersion> ret = new HashMap<>();
        Set<String> strings = projectDTOMap.keySet();
        for (String string : strings) {
            ProjectVersion versionByName = findVersionByName(string);
            if (versionByName != null) {
                ret.put(string, versionByName);
            }
        }
        return ret;
    }

    public static ProjectVersion findVersionByName(String name) {
        ProjectDTO projectDTO = projectDTOMap.get(name);
        String content = readFile2Content(projectDTO.getPath());
        if (!StringUtils.hasText(content)) {
            return null;
        }
        ProjectVersion projectVersion = new ProjectVersion();
        Matcher matcher = bomCompile.matcher(content);
        if (matcher.find()) {
            String bom = matcher.group(0);
            if (bom.contains("\"")) {
                bom = bom.substring(bom.indexOf("\"") + 1, bom.lastIndexOf("\""));
            } else {
                bom = bom.substring(bom.indexOf("'") + 1, bom.lastIndexOf("'"));
            }
            String[] split = bom.split(":");
            if (split.length == 3) {
                projectVersion.setBomVersion(split[2].trim());
                compareBigVersion(split[2].trim().split("-")[0]);
            }
        } else {
            projectVersion.setBomVersion("无");
        }
        matcher = versionCompile.matcher(content);
        if (matcher.find()) {
            String version = matcher.group(0);
            if (version.contains("\"")) {
                version = version.substring(version.indexOf("\"") + 1, version.lastIndexOf("\""));
            } else {
                version = version.substring(version.indexOf("'") + 1, version.lastIndexOf("'"));
            }
            projectVersion.setVersion(version.trim());
        } else {
            projectVersion.setVersion("无");
        }
        return projectVersion;
    }

    public static void replaceBomVersion(String newVersion) {
        if (!StringUtils.hasText(newVersion)) {
            return;
        }
        if (MapUtils.isEmpty(projectDTOMap)) {
            return;
        }
        Set<String> strings = projectDTOMap.keySet();
        for (String string : strings) {
            replaceBomVersionByName(newVersion, string);
        }
    }

    public static void replaceBomVersionByName(String newVersion, String name) {
        Pattern bomCompile = Pattern.compile(BOM_REGX);
        Pattern versionCompile = Pattern.compile(VERSION_REGX);
        ProjectDTO projectDTO = projectDTOMap.get(name);
        String content = readFile2Content(projectDTO.getPath());
        if (!StringUtils.hasText(content)) {
            return;
        }
        Matcher matcher = bomCompile.matcher(content);
        if (matcher.find()) {
            String oldBom = matcher.group(0);
            String oldVersion = "";
            if (oldBom.contains("\"")) {
                oldVersion = oldBom.substring(oldBom.indexOf("\"") + 1, oldBom.lastIndexOf("\""));
            } else {
                oldVersion = oldBom.substring(oldBom.indexOf("'") + 1, oldBom.lastIndexOf("'"));
            }
            String[] split = oldVersion.split(":");
            if (split.length == 3) {
                oldVersion = split[2].trim();
                String newBom = oldBom.replace(oldVersion, newVersion);
                System.out.println("》》》 变更bom版本号成功 " + projectDTO.getName() + " 由 " + oldVersion + " 变更为 " + newVersion + "\r\n");
                content = content.replace(oldBom, newBom);
            }
        }
        matcher = versionCompile.matcher(content);
        if (matcher.find()) {
            String oldVersion = matcher.group(0);
            String oldVersionContent = "";
            if (oldVersion.contains("\"")) {
                oldVersionContent = oldVersion.substring(oldVersion.indexOf("\"") + 1, oldVersion.lastIndexOf("\""));
            } else {
                oldVersionContent = oldVersion.substring(oldVersion.indexOf("'") + 1, oldVersion.lastIndexOf("'"));
            }
            if (StringUtils.hasText(oldVersionContent)) {
                oldVersionContent = oldVersionContent.trim();
                String newVersionText = oldVersion.replace(oldVersionContent, newVersion);
                content = content.replace(oldVersion, newVersionText);
            }
        }
        writeContent2File(projectDTO.getPath(), content);
    }

    public static void delProject(String basePath) {
        File file = new File(basePath);
        if (file.isFile()) {
            file.delete();
            return;
        }
        File[] files = file.listFiles();
        for (File file1 : files) {
            if (file1.isFile()) {
                file1.delete();
            } else {
                delProject(file1.getAbsolutePath());
            }
        }
        file.delete();
    }

    public static void compareBigVersion(String version) {
        String[] split = maxVersion.split("\\.");
        String[] split1 = version.split("\\.");
        for (int i = 0; i < split.length; i++) {
            Integer maxVersionIndex = Integer.parseInt(split[i]);
            Integer versionIndex = Integer.parseInt(split1[i]);
            if (maxVersionIndex > versionIndex) {
                return;
            } else if (maxVersionIndex == versionIndex) {
                continue;
            } else if (maxVersionIndex < versionIndex){
                int lastVersion = Integer.parseInt(split1[2]) + 1;
                maxVersion = "";
                for (int i1 = 0; i1 < 3; i1++) {
                    if (i1 != 2) {
                        maxVersion += split1[i1] + ".";
                    }
                }
                maxVersion += lastVersion;
                return;
            }
        }
    }

    public static void reloadConfig() {
        resetConfig();
        initGitData();
        initProject();
    }

    public static void resetConfig() {
        writeContent2File(PathManagerUtil.configPath, JsonUtil.toJsonString(configDTO));
    }
}
